package model

import (
	"context"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
	"hc/app"
	"sync"
)

var db = app.GetDB()
var orderDB = app.GetOrderDB()
var orderBinaryTreeDB = app.GetOrderBinaryTreeDB()
var cache = app.GetCache()
var mq = app.GetMQ()
var mqs = app.GetMQS()
var etcd = app.GetEtcd()

var orderTableCount = 16
var orderDBCount = len(orderDB)
var mqsCount = len(mqs)
var orderBinaryTreeDBCount = len(orderBinaryTreeDB)


var stockOutEtcdPrefix = "/goods/stock/"
var stockOut sync.Map
var stockOutPrefix = "stockOut"


func init() {

	//go watchStockOut()
}

func watchStockOut () {
	// 监控目录
	kv := clientv3.NewKV(etcd)
	getResponse, err := kv.Get(context.TODO(), stockOutEtcdPrefix, clientv3.WithPrefix())
	if err != nil {
		panic(err)
	}

	for _, item := range getResponse.Kvs {
		fmt.Println("获取数据：", string(item.Key), string(item.Value))
	}

	startRevision := getResponse.Header.Revision + 1
	watcher := clientv3.NewWatcher(etcd)

	watchResponseChan := watcher.Watch(context.TODO(), stockOutEtcdPrefix, clientv3.WithPrefix(), clientv3.WithRev(startRevision))

	for res := range watchResponseChan {
		for _, event := range res.Events {
			switch event.Type {
			case mvccpb.PUT:
				fmt.Println("更新为：", "Value:", string(event.Kv.Value), "Revision:", event.Kv.CreateRevision, event.Kv.ModRevision)
				//stockOut.Store("1", "test")
			case mvccpb.DELETE:
				fmt.Println("删除了：", "Value:", string(event.Kv.Value), "Key:", string(event.Kv.Key), "Revision:", event.Kv.ModRevision)
				key := string(event.Kv.Key)[len(stockOutEtcdPrefix):]
				stockOut.Delete(stockOutPrefix + key)
			}
		}
	}
}

func stockOutDelete(goodsId int) {
	stockOut.Delete(getStockOutKey(goodsId))

	kv := clientv3.NewKV(etcd)
	_, err := kv.Delete(context.TODO(), fmt.Sprintf("%s%d", stockOutEtcdPrefix, goodsId))
	if err != nil {
		fmt.Println("failed, err:", err)
		return
	}
}

func getStockOutKey(goodsId int) string {
	return fmt.Sprintf("%s%d", stockOutPrefix, goodsId)
}

func GetStockOut(goodsId int) (interface{}, bool) {
	return stockOut.Load(getStockOutKey(goodsId))
}

func checkStock(goodsId int, number int) bool {

	key := fmt.Sprintf("goods:%d", goodsId)

	stock, err := cache.HIncrBy(key, "stock", -int64(number)).Result()
	if err != nil {
		//log.Fatal(err)
		return false
	}
	if stock < 0 {
		incrStock(goodsId, number)
		return false
	}

	return true
}

func incrStock(goodsId int, number int)  {
	key := fmt.Sprintf("goods:%d", goodsId)
	cache.HIncrBy(key, "stock", int64(number))
}

